package edu.bu.cs673.superkids123.children.controller.lessons;

import java.lang.reflect.InvocationTargetException;

import javax.swing.ImageIcon;
import javax.swing.SwingUtilities;

import edu.bu.cs673.superkids123.AbstractFrame;
import edu.bu.cs673.superkids123.children.DataObjectAccess.LessonGameManager;
import edu.bu.cs673.superkids123.children.controller.AbstractLessonController;
import edu.bu.cs673.superkids123.children.model.Lesson;
import edu.bu.cs673.superkids123.children.model.resources.AudioPlayer;
import edu.bu.cs673.superkids123.children.model.resources.ChildrenResource;
import edu.bu.cs673.superkids123.children.model.resources.ChildrenResourceProvider;
import edu.bu.cs673.superkids123.children.view.ActivitiesMenuView;
import edu.bu.cs673.superkids123.children.view.lessons.AddingLessonView;
import edu.bu.cs673.superkids123.children.view.lessons.CountingLessonView;
import edu.bu.cs673.superkids123.children.view.lessons.LessonResultsView;

/**
 * Class AddingLessonController
 * 
 * This is the controller class that supports the adding lesson.
 * This follows David Bardwell's pattern for the counting lesson.
 * 
 * @author Ted Atkinson
 * 
 */

public class AddingLessonController extends AbstractLessonController {

        private final int minAddend = 1;
        private final int maxAddend = 10;
        private final int numberOfScreenGroups = 10;
        private int leftNumber = 1, rightNumber = 1;
        private boolean stopPlay = false;
        ChildrenResourceProvider provider = ChildrenResourceProvider.getInstance();

        public AddingLessonController(AbstractFrame mainFrame) {
                super(mainFrame);
        }
        
        public int getLeftNumber() {
                return leftNumber;
        }
        
        public int getRightNumber() {
                return rightNumber;
        }
        
        public int getSum() {
                return leftNumber + rightNumber;
        }
        
        public void setStopPlay(boolean stopState) {
                stopPlay = stopState;
        }
        
        public boolean getStopPlay() {
                return stopPlay;
        }
        
        /**
         * More/Less Number Buttons
         * Increase or decrease either addend in the given range of minAddend
         * to maxAddend.
         * 
         * @param AddingLessonView view
         * 
         */
        public void moreButtonLeftPressed(AddingLessonView view) {
                final AddingLessonView view2 = view;
                view2.setBusy(true);
                
                Thread myLeftIncThread = new Thread() {
                        public void run() {
                                if (leftNumber < maxAddend) {
                                        leftNumber++;
                                        forceRepaintInThread(view2);
                                        
                                        try {
                                                SwingUtilities.invokeAndWait(new Runnable() {
                                                    public void run() {
                                                        view2.initializeAddingButtons();
                                                        view2.showAddingButtons();
                                                    }
                                                });
                                        } catch (InterruptedException e) {
                                                // TODO Auto-generated catch block
                                                e.printStackTrace();
                                        } catch (InvocationTargetException e) {
                                                // TODO Auto-generated catch block
                                                e.printStackTrace();
                                        }
                                }
                                view2.setBusy(false);
                        }
                };
                myLeftIncThread.start();
        }
        
        public void lessButtonLeftPressed(AddingLessonView view) {
                final AddingLessonView view2 = view;
                view2.setBusy(true);
                
                Thread myLeftDecThread = new Thread() {
                        public void run() {
                                if (leftNumber > minAddend) {
                                        leftNumber--;
                                        forceRepaintInThread(view2);
                                        
                                        try {
                                                SwingUtilities.invokeAndWait(new Runnable() {
                                                    public void run() {
                                                        view2.initializeAddingButtons();
                                                        view2.showAddingButtons();
                                                    }
                                                });
                                        } catch (InterruptedException e) {
                                                // TODO Auto-generated catch block
                                                e.printStackTrace();
                                        } catch (InvocationTargetException e) {
                                                // TODO Auto-generated catch block
                                                e.printStackTrace();
                                        }
                                }
                                view2.setBusy(false);
                        }
                };
                myLeftDecThread.start();
        }
        
        public void moreButtonRightPressed(AddingLessonView view) {
                final AddingLessonView view2 = view;
                view2.setBusy(true);
                
                Thread myRightIncThread = new Thread() {
                        public void run() {
                                if (rightNumber < maxAddend) {
                                        rightNumber++;
                                        forceRepaintInThread(view2);
                                        
                                        try {
                                                SwingUtilities.invokeAndWait(new Runnable() {
                                                    public void run() {
                                                        view2.initializeAddingButtons();
                                                        view2.showAddingButtons();
                                                    }
                                                });
                                        } catch (InterruptedException e) {
                                                // TODO Auto-generated catch block
                                                e.printStackTrace();
                                        } catch (InvocationTargetException e) {
                                                // TODO Auto-generated catch block
                                                e.printStackTrace();
                                        }
                                }
                                view2.setBusy(false);
                        }
                };
                myRightIncThread.start();
        }
        
        public void lessButtonRightPressed(AddingLessonView view) {
                final AddingLessonView view2 = view;
                view2.setBusy(true);
                
                Thread myRightDecThread = new Thread() {
                        public void run() {
                                if (rightNumber > minAddend) {
                                        rightNumber--;
                                        forceRepaintInThread(view2);
                                        
                                        try {
                                                SwingUtilities.invokeAndWait(new Runnable() {
                                                    public void run() {
                                                        view2.initializeAddingButtons();
                                                        view2.showAddingButtons();
                                                    }
                                                });
                                        } catch (InterruptedException e) {
                                                // TODO Auto-generated catch block
                                                e.printStackTrace();
                                        } catch (InvocationTargetException e) {
                                                // TODO Auto-generated catch block
                                                e.printStackTrace();
                                        }
                                }
                                view2.setBusy(false);
                        }
                };
                myRightDecThread.start();
        }
                
        /**
         * playButtonPressed
         * 
         * Separate threads are needed to make this work correctly. The
         * event dispatch thread on which the play button action starts, must
         * terminate so the paint activity on the panel can work correctly. 
         * 
         * @param AddingLessonView view
         */
        public void playButtonPressed(AddingLessonView view) {
                final AddingLessonView view2 = view;
                view2.setBusy(true);
                
                Thread myPlayThread = new Thread() {
                        public void run() {
                                AddingLessonController.this.setStopPlay(false);
                        
                            forceRepaintInThread(view2);
                                
                            // Check if user stopped play, if so, abort
                            if (AddingLessonController.this.getStopPlay() == true) {
                                        forceRepaintInThread(view2);
                                        view2.setBusy(false);
                                        return;
                            }
                        
                            playAudioForSum(leftNumber, rightNumber, view2);
                            view2.setBusy(true);
                                                        
                            try {
                                        SwingUtilities.invokeAndWait(new Runnable() {
                                            public void run() {
                                                view2.initializeAddingButtons();
                                                view2.showAddingButtons();
                                            }
                                        });
                                } catch (InterruptedException e) {
                                        // TODO Auto-generated catch block
                                        e.printStackTrace();
                                } catch (InvocationTargetException e) {
                                        // TODO Auto-generated catch block
                                        e.printStackTrace();
                                }
                        
                                forceRepaintInThread(view2);
                                view2.setBusy(false);
                        }
                };
                myPlayThread.start();
        }
        
        private void forceRepaintInThread(AddingLessonView view) {
                final AddingLessonView view2 = view;
                    Thread myRepaintThread = new Thread() {
                        public void run() {
                                view2.repaintAddingPanel();
                        }
                };
            // Important: Swing is not thread safe, must always use
                // SwingUtilities if not the event dispatch thread.
                SwingUtilities.invokeLater(myRepaintThread);
        }
        
        private void playAudioForSum(int number, int number2, AddingLessonView view) {
                AudioPlayer audioPlayer = new AudioPlayer();
                byte[] audioDataLeft = getAudioSampledData(number);
                byte[] audioDataPlus = getAudioSampledData("plus");
                byte[] audioDataRight = getAudioSampledData(number2);
                byte[] audioDataEquals = getAudioSampledData("equals");
                byte[] audioDataSum = getAudioSampledData(number + number2);
                byte[][] audioData = {
                        audioDataLeft, audioDataPlus, audioDataRight, 
                        audioDataEquals, audioDataSum
                };
                                        
                for (int i = 0; i < audioData.length; i++) {
                        audioPlayer.playAudio(audioData[i]);
                        
                        try {
                                Thread.sleep(100);
                        }
                        catch (InterruptedException ie) {
                                System.out.println("Thread interrupted");
                        }
                };
                view.setBusy(false);
        }
        
        public ImageIcon getImageIcon(int numberToShow) {
                String resourceImageId = null;
                
                resourceImageId = ChildrenResource.NUMBER_IMAGE_MAP.get(numberToShow);
                
                // Get the numberIcon from the resource to display 
                ImageIcon numberImageIcon = null;
                numberImageIcon = provider.getScaledImage(resourceImageId, 0.7f);
              
                return numberImageIcon;
        }
        
        public ImageIcon getImageIcon(String symbolToShow) {
                String resourceImageId = null;
                
                resourceImageId = ChildrenResource.SYMBOL_IMAGE_MAP.get(symbolToShow);
                
                // Get the symbolIcon from the resource to display 
                ImageIcon symbolImageIcon = null;
                symbolImageIcon = provider.getScaledImage(resourceImageId, 0.8f);
                
                return symbolImageIcon;
        }
        
        public byte[] getAudioSampledData(int numberToPlay) {
                byte[] audioData = null;
                
                audioData = provider.getAudioContentByNumber(numberToPlay);
                return audioData;
        }
        
        public byte[] getAudioSampledData(String symbolToPlay) {
                byte[] audioData = null;
                
                audioData = provider.getAudioContentBySymbol(symbolToPlay);
                return audioData;
        }
        
        public void startLesson() {        	
        	for (Lesson l : LessonGameManager.getAllLessons()) {
        		if (l.getName().contains("Add"))
        			start(l);
        	}
        }
        
        public void stopLesson(boolean complete) {
        	if (isActive())
        		stop(complete);
        }
}